#ifndef __SUBSYSTEM_METERS_BLOCK_BEHAVIOR_H__
#define __SUBSYSTEM_METERS_BLOCK_BEHAVIOR_H__

#include "SubsystemBlockBehavior.hpp"
#include <map>
#include <mutex>

namespace PocketSurvival
{
    class SubsystemWeather;
    class SubsystemTimeOfDay;
    class SubsystemTerrain;

    class SubsystemMetersBlockBehavior : public SubsystemBlockBehavior
    {
    protected:
        SubsystemWeather *m_weather;
        SubsystemTimeOfDay *m_timeOfDay;
        SubsystemTerrain *m_terrain;

        std::map<Point3, int32_t> m_thermometersByPoint;
        std::mutex m_thermometersByPointMutex;

        std::vector<Point3> m_thermometersToSimulate;
        int32_t m_thermometersToSimulateIndex;
        
    public:
        int32_t getThermometerReading(const Point3& point);
        inline int32_t getThermometerReading(int32_t x, int32_t y, int32_t z);
        void calculateTemperature(int32_t x, int32_t y, int32_t z, float meterTemperature, float meterInsulation, float &outTemperature, float &outTemperatureFlux);
        float getHeat(int32_t value);
        void simulateThermometer(int32_t x, int32_t y, int32_t z, bool invalidateTerrainOnChange);
        void addMeter(int32_t value, int32_t x, int32_t y, int32_t z);
        void removeMeter(int32_t value, int32_t x, int32_t y, int32_t z);


        virtual void onNeighborBlockChanged(int32_t x, int32_t y, int32_t z, int32_t neighborX, int32_t neighborY, int32_t neighborZ) override;
        virtual void onBlockGenerated(int32_t value, int32_t x, int32_t y, int32_t z, bool isLoaded) override;
        virtual void onBlockAdded(int32_t value, int32_t oldValue, int32_t x, int32_t y, int32_t z) override;
        virtual void onBlockRemoved(int32_t value, int32_t newValue, int32_t x, int32_t y, int32_t z) override;
        virtual void onBlockModified(int32_t value, int32_t oldValue, int32_t x, int32_t y, int32_t z) override;
        virtual void onChunkDiscarding(TerrainChunk *chunk) override;

    public:
        SubsystemMetersBlockBehavior();

        virtual void update(float dt) override;
        virtual void load(const nlohmann::json &json) override;
        virtual const std::string& getName() const override;
        virtual SubUpdateType getUpdateType() override;
    };

    inline int32_t SubsystemMetersBlockBehavior::getThermometerReading(int32_t x, int32_t y, int32_t z)
    {
        return getThermometerReading(Point3(x, y, z));
    }
}

#endif